﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using wrsm.wow.entity;
using wrsm.wow.exceptions;

namespace wrsm.wow {

    /// <summary>
    /// World of Warcraft Installation Utility,
    /// Provides functionality required to detect and analyse World of Warcraft Installation
    /// </summary>
    [CLSCompliant(true)]
    public class WowInstallationUtility {

        /// <summary>
        /// Use the Hints in Application Configuration file, to determine where 
        /// World of Warcraft is installed on this machine.
        /// </summary>
        /// <returns>World of Warcraft Installation</returns>
        public WowInstallation LocateWowInstallationDirectory() {
            string[] hints = ConfigurationManager.AppSettings["wrsm.wow.io.path.wow.hint"].Split(new char[] { '|' },
                                                                                       StringSplitOptions.RemoveEmptyEntries);
            foreach (string path in hints) {
                WowInstallation wowInst = new WowInstallation() { InstallLocation = path };
                if (IsValidWowInstall(wowInst)) {
                    wowInst.ValidInstall = true;
                    wowInst.Accounts = GetAccounts(wowInst);
                    return wowInst;
                }
            }
            throw new WowApplicationException("Unable to locate a Valid World of Warcraft installation.");
        }

        /// <summary>
        /// Use specified path, to load wow installation directory
        /// </summary>
        /// <returns>a World of Warcraft Installation object</returns>
        public WowInstallation LoadInstallationDirectory(string location) {
            WowInstallation wowInst = new WowInstallation() { InstallLocation = location };
            if (IsValidWowInstall(wowInst)) {
                wowInst.ValidInstall = true;
                wowInst.Accounts = GetAccounts(wowInst);
            } else {
                wowInst.ValidInstall = false;
            }
            return wowInst;
        }

        /// <summary>
        /// Simply check the specified path, to exist, and that it contains all required files/directories
        /// </summary>
        /// <param name="install">A World of Warcraft Installation</param>
        /// <returns>boolean value.  Indicating whether or not this directory has enough information 
        /// to be considered a valid world of warcraft installation.</returns>
        public bool IsValidWowInstall(WowInstallation install) {
            //Pull a list of all required assets from the configuration file
            string[] requiredAssets = ConfigurationManager.AppSettings["wrsm.wow.io.path.wow.requiredAssets"].Split(new char[] { '|' });
            //Scan directory for each required asset
            foreach (string requiredAsset in requiredAssets) {
                string fullAssetPath = Path.Combine(install.InstallLocation, requiredAsset);
                //Test if we're looking for a directory
                if (requiredAsset.Trim().EndsWith("/")) {
                    if (!Directory.Exists(fullAssetPath)) {
                        return false;
                    }
                } else {
                    if (!File.Exists(fullAssetPath)) {
                        return false;
                    }
                }
            }
            //We would have already exited by now if anything was missing, so consider this a valid path
            return true;
        }

        /// <summary>
        /// Get a list of accounts detected in a Wow Installation Directory
        /// </summary>
        /// <param name="install">Wow Installation</param>
        /// <returns>an array of strings, containing account numbers</returns>
        public WowAccount[] GetAccounts(WowInstallation install) {
            List<WowAccount> accounts = new List<WowAccount>();
            string[] accountDirectories = Directory.GetDirectories(Path.Combine(install.InstallLocation, "WTF/Account"));
            foreach (string accountDirectory in accountDirectories) {
                WowAccount account = new WowAccount();
                account.AccountNumber = Path.GetFileName(accountDirectory);
                account.Realms = GetRealmsForAccount(install, account);
                accounts.Add(account);
            }
            return accounts.ToArray();
        }

        /// <summary>
        /// Get a list of realms detected in a wow install directory, by account number
        /// </summary>
        /// <param name="install">Wow Installation</param>
        /// <param name="account">Wow Account</param>
        /// <returns>Array of realms for account</returns>
        public WowRealm[] GetRealmsForAccount(WowInstallation install, WowAccount account) {
            List<WowRealm> realms = new List<WowRealm>();
            string[] realmDirectories = Directory.GetDirectories(Path.Combine(install.InstallLocation, "WTF/Account", account.AccountNumber));
            foreach (string realmDirectory in realmDirectories) {
                WowRealm realm = new WowRealm();
                realm.RealmName = Path.GetFileName(realmDirectory);
                realm.Characters = GetCharactersForAccountByRealm(install, account, realm);
                realms.Add(realm);
            }
            return realms.ToArray();
        }

        /// <summary>
        /// Get a list of all characters detected in a wow install directory,
        /// by account number, and realm
        /// </summary>
        /// <param name="install">Wow Install</param>
        /// <param name="account">Wow Account</param>
        /// <param name="realm">Wow Realm</param>
        /// <returns>Array of characters on a particular realm</returns>
        public WowCharacter[] GetCharactersForAccountByRealm(WowInstallation install, WowAccount account, WowRealm realm) {
            List<WowCharacter> characters = new List<WowCharacter>();
            string[] characterDirectories = Directory.GetDirectories(Path.Combine(install.InstallLocation, "WTF/Account", account.AccountNumber, realm.RealmName));
            foreach (string characterName in characterDirectories) {
                WowCharacter character = new WowCharacter();
                character.CharacterName = Path.GetFileName(characterName);
                characters.Add(character);
            }
            return characters.ToArray();
        }
    }
}
